/*
 * Editor.java
 *
 * Created on 06.11.2008., 18.40
 */

package rs.fon.rapidminer.gui.editor;

import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;

import rs.fon.rapidminer.process.Parameter;
import rs.fon.rapidminer.process.ParameterReader;
import rs.fon.rapidminer.process.Step;
import rs.fon.rapidminer.process.StepData;

/**
 * 
 * @author Sasa
 */
public abstract class EditorPanel extends javax.swing.JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8141066767385529563L;
	/**
	 * Variables used for labeling. Currently in use because of lack of author's
	 * imagination so change is probable.
	 */
	private static final String NAME_LABEL = "Name of the step: ";
	private static final String DESCRIPTION_LABEL = "Description of the step: ";
	private static final String IS_MULTIPLE_LABEL = "Is the step multiple: ";
	private static final String SELECT_IMPLEMENTATION_LABEL = "Select concrete step: ";
	private static final String PARAMETERS_LABEL = "Parameters: ";

	/** Step which information is drawn **/
	private Step step;

	/** Creates new form Editor */
	public EditorPanel() {
		initComponents();
	}

	protected abstract void performAction();

	public void load(Step step) {
		this.step = step;
		drawAll();
		if (step.getMultipleStepData() != null || step.getStepData() != null)
			fireItemsSelected();
		else
			parameters1.preparePanel();
	}

	protected void drawAll() {
		setStepName();
		setDescription();
		setIsMultiple();
		setList();
		setSelectedListItem();
	}

	private void fireItemsSelected() {
		try {
			if (step.isMultiple()) {
				parameters1.load(getSelectedClasses(), step
						.getMultipleStepData());
			} else {
				parameters1.load(getSelectedClasses(), step.getStepData());
			}
		} catch (Exception e) {
			// Do nothing. Thrown if new process selected
			System.err.println("fireItemsSelected: " + e);
		}
	}

	private void setDescription() {
		if (step == null)
			this.description.setText("");
		else
			this.description.setText(step.getDescription());
	}

	private void setIsMultiple() {
		if (step == null) {
			this.isMultiple.setSelected(false);
		} else {

			this.isMultiple.setSelected(step.isMultiple());
			if (isMultiple.isSelected()) {
				list
						.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
			} else {
				list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			}
		}
	}

	private void setSelectedListItem() {
		if (step == null)
			return;

		if (step.getMultipleStepData() == null && step.getStepData() == null) // Means
			// this
			// step
			// was
			// never
			// saved
			// before
			return;

		try {
			if (!isMultiple.isSelected()) {
				System.out.println("SAVED IMPL CLASS: "
						+ step.getStepData().getNameOfImplementationClass());
				list.setSelectedValue(step.getStepData()
						.getNameOfImplementationClass(), true);
			} else {
				List<StepData> multiStepData = step.getMultipleStepData();
				int numOfSelections = multiStepData.size();
				String[] classes = new String[numOfSelections];

				int i = 0;
				for (StepData data : multiStepData) {
					classes[i++] = data.getNameOfImplementationClass();
				}

				int[] indices = new int[numOfSelections];

				i = 0;
				int j = 0;
				for (String s : step.getAvailableImplementationClassNames()) {

					for (String l : classes) {
						if (s.equals(l))
							indices[i++] = j;
					}

					j++;
				}

				list.setSelectedIndices(indices);

			}
		} catch (NullPointerException ne) {
			// If step shown but no implementation selected, doesn't cause
			// problems
		}
	}

	private void setStepName() {
		if (step == null)
			this.name.setText("");
		else
			this.name.setText(step.getName());
	}

	private void setList() {
		if (step == null) {
			this.list.setModel(new DefaultListModel());
		} else {

			final String[] availableClasses = step
					.getAvailableImplementationClassNames();

			DefaultListModel listModel = new DefaultListModel();
			for (String s : availableClasses) {
				listModel.addElement(s);
			}
			list.setModel(listModel);
		}
	}

	protected Class[] getSelectedClasses() {
		try {
			int[] indices = list.getSelectedIndices();
			Class[] selectedClasses = new Class[indices.length];
			String[] availableClasses = step
					.getAvailableImplementationClassNames();

			for (int i = 0; i < indices.length; i++) {
				selectedClasses[i] = Class
						.forName(availableClasses[indices[i]]);
			}

			return selectedClasses;
		} catch (ClassNotFoundException ex) {
			Logger.getLogger(EditorPanel.class.getName()).log(Level.SEVERE,
					null, ex);
		}
		return null;
	}

	private void saveStep() {

		List<Parameter> oldParams = null;
		try {
			oldParams = parameters1.getParams();
		} catch (Exception e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
			return;
		}

		// Clone the list of params
		List<Parameter> params = new LinkedList<Parameter>();
		for (int i = 0; i < oldParams.size(); i++) {
			try {
				System.out.println("VALUE AND TYPE: "
						+ oldParams.get(i).getXenteredValue()
						+ oldParams.get(i).getParametertType());
				params.add((Parameter) oldParams.get(i).clone());
			} catch (CloneNotSupportedException ex) {
				Logger.getLogger(EditorPanel.class.getName()).log(Level.SEVERE,
						null, ex);
			}
		}

		System.out.println("GP:::Saving step " + step.getName() + " which is "
				+ (step.isMultiple() ? "multiple" : "not multiple") + ".");
		System.out.print("GP:::Params entered values to be saved are: ");
		for (Parameter p : params)
			System.out.print(p.getXenteredValue() + " ");
		System.out.println(".");

		if (!step.isMultiple()) {
			StepData sd = new StepData();
			sd.setListOfParameters(params);
			sd.setNameOfImplementationClass(getSelectedClasses()[0].getName());
			System.out.println("GP:::Saving single step data: "
					+ sd.getNameOfImplementationClass() + " with "
					+ sd.getListOfParameters().size() + " params.");
			step.setStepData(sd);
		} else {
			List<StepData> stepData = new LinkedList<StepData>();
			Class[] selectedClases = getSelectedClasses();
			List<Parameter> helperList;
			int counter = 0; // count number of params of each class for
			// skipping
			int lastPosition = 0; // remembers the last edited param index
			for (Class c : selectedClases) {
				counter = ParameterReader.readParameters(c).size();
				StepData sd = new StepData();
				helperList = new LinkedList<Parameter>();
				for (int i = lastPosition; i < lastPosition + counter; i++) {
					helperList.add(params.get(i));
				}
				sd.setListOfParameters(helperList);
				sd.setNameOfImplementationClass(c.getName());
				stepData.add(sd);
				lastPosition += counter;
			}
			step.setMultipleStepData(stepData);
		}

		performAction();
	}

	private void disableStep() {

		System.out.println("GP:::Disabling step " + step.getName()
				+ " which is "
				+ (step.isMultiple() ? "multiple" : "not multiple") + ".");

		if (!step.isMultiple()) {
			step.setStepData(null);
		} else {
			step.setMultipleStepData(null);
		}

		load(step);
		performAction();
	}

	public void restart() {
		step = null;
		drawAll();
		parameters1.preparePanel();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed"
	// desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {

		jLabel1 = new javax.swing.JLabel();
		jLabel2 = new javax.swing.JLabel();
		jLabel3 = new javax.swing.JLabel();
		name = new javax.swing.JLabel();
		description = new javax.swing.JLabel();
		isMultiple = new javax.swing.JCheckBox();
		jLabel4 = new javax.swing.JLabel();
		jScrollPane1 = new javax.swing.JScrollPane();
		list = new javax.swing.JList();
		jLabel5 = new javax.swing.JLabel();
		parameters1 = new rs.fon.rapidminer.gui.editor.Parameters();
		jButton1 = new javax.swing.JButton();
		jButton2 = new javax.swing.JButton();

		jLabel1.setText(NAME_LABEL);

		jLabel2.setText(DESCRIPTION_LABEL);

		jLabel3.setText(IS_MULTIPLE_LABEL);

		name.setText(" ");

		description.setText(" ");

		isMultiple.setEnabled(false);

		jLabel4.setText(SELECT_IMPLEMENTATION_LABEL);

		list
				.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
					public void valueChanged(
							javax.swing.event.ListSelectionEvent evt) {
						listValueChanged(evt);
					}
				});
		jScrollPane1.setViewportView(list);

		jLabel5.setText(PARAMETERS_LABEL);

		parameters1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

		javax.swing.GroupLayout parameters1Layout = new javax.swing.GroupLayout(
				parameters1);
		parameters1.setLayout(parameters1Layout);
		parameters1Layout.setHorizontalGroup(parameters1Layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGap(0, 396, Short.MAX_VALUE));
		parameters1Layout.setVerticalGroup(parameters1Layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGap(0, 91, Short.MAX_VALUE));

		jButton1.setText("Save step");
		jButton1.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton1ActionPerformed(evt);
			}
		});

		jButton2.setText("Disable step");
		jButton2.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton2ActionPerformed(evt);
			}
		});

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
		this.setLayout(layout);
		layout
				.setHorizontalGroup(layout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								layout
										.createSequentialGroup()
										.addContainerGap()
										.addGroup(
												layout
														.createParallelGroup(
																javax.swing.GroupLayout.Alignment.LEADING)
														.addComponent(
																parameters1,
																javax.swing.GroupLayout.DEFAULT_SIZE,
																javax.swing.GroupLayout.DEFAULT_SIZE,
																Short.MAX_VALUE)
														.addGroup(
																layout
																		.createSequentialGroup()
																		.addGroup(
																				layout
																						.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.LEADING)
																						.addComponent(
																								jLabel1)
																						.addComponent(
																								jLabel2)
																						.addComponent(
																								jLabel3)
																						.addComponent(
																								jLabel4))
																		.addGap(
																				28,
																				28,
																				28)
																		.addGroup(
																				layout
																						.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.TRAILING)
																						.addComponent(
																								jScrollPane1,
																								javax.swing.GroupLayout.DEFAULT_SIZE,
																								306,
																								Short.MAX_VALUE)
																						.addGroup(
																								layout
																										.createSequentialGroup()
																										.addGroup(
																												layout
																														.createParallelGroup(
																																javax.swing.GroupLayout.Alignment.LEADING)
																														.addGroup(
																																layout
																																		.createSequentialGroup()
																																		.addGroup(
																																				layout
																																						.createParallelGroup(
																																								javax.swing.GroupLayout.Alignment.TRAILING)
																																						.addComponent(
																																								description,
																																								javax.swing.GroupLayout.DEFAULT_SIZE,
																																								183,
																																								Short.MAX_VALUE)
																																						.addComponent(
																																								name,
																																								javax.swing.GroupLayout.DEFAULT_SIZE,
																																								183,
																																								Short.MAX_VALUE))
																																		.addPreferredGap(
																																				javax.swing.LayoutStyle.ComponentPlacement.RELATED))
																														.addGroup(
																																layout
																																		.createSequentialGroup()
																																		.addComponent(
																																				isMultiple)
																																		.addGap(
																																				166,
																																				166,
																																				166)))
																										.addGroup(
																												layout
																														.createParallelGroup(
																																javax.swing.GroupLayout.Alignment.LEADING,
																																false)
																														.addComponent(
																																jButton2,
																																javax.swing.GroupLayout.DEFAULT_SIZE,
																																javax.swing.GroupLayout.DEFAULT_SIZE,
																																Short.MAX_VALUE)
																														.addComponent(
																																jButton1,
																																javax.swing.GroupLayout.DEFAULT_SIZE,
																																119,
																																Short.MAX_VALUE)))))
														.addComponent(jLabel5))
										.addContainerGap()));
		layout
				.setVerticalGroup(layout
						.createParallelGroup(
								javax.swing.GroupLayout.Alignment.LEADING)
						.addGroup(
								layout
										.createSequentialGroup()
										.addGroup(
												layout
														.createParallelGroup(
																javax.swing.GroupLayout.Alignment.LEADING)
														.addGroup(
																layout
																		.createSequentialGroup()
																		.addContainerGap()
																		.addGroup(
																				layout
																						.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.LEADING)
																						.addGroup(
																								layout
																										.createSequentialGroup()
																										.addComponent(
																												jLabel1)
																										.addPreferredGap(
																												javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																										.addGroup(
																												layout
																														.createParallelGroup(
																																javax.swing.GroupLayout.Alignment.BASELINE)
																														.addComponent(
																																jLabel2)
																														.addComponent(
																																description)))
																						.addGroup(
																								layout
																										.createParallelGroup(
																												javax.swing.GroupLayout.Alignment.BASELINE)
																										.addComponent(
																												name)
																										.addComponent(
																												jButton1,
																												javax.swing.GroupLayout.PREFERRED_SIZE,
																												33,
																												javax.swing.GroupLayout.PREFERRED_SIZE)))
																		.addGap(
																				24,
																				24,
																				24)
																		.addGroup(
																				layout
																						.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.LEADING)
																						.addGroup(
																								layout
																										.createSequentialGroup()
																										.addComponent(
																												jLabel3)
																										.addPreferredGap(
																												javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																										.addComponent(
																												jLabel4))
																						.addGroup(
																								layout
																										.createSequentialGroup()
																										.addComponent(
																												isMultiple)
																										.addPreferredGap(
																												javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																										.addComponent(
																												jScrollPane1,
																												javax.swing.GroupLayout.PREFERRED_SIZE,
																												107,
																												javax.swing.GroupLayout.PREFERRED_SIZE)))
																		.addGap(
																				10,
																				10,
																				10)
																		.addComponent(
																				jLabel5)
																		.addGap(
																				18,
																				18,
																				18)
																		.addComponent(
																				parameters1,
																				javax.swing.GroupLayout.DEFAULT_SIZE,
																				javax.swing.GroupLayout.DEFAULT_SIZE,
																				Short.MAX_VALUE))
														.addGroup(
																layout
																		.createSequentialGroup()
																		.addGap(
																				52,
																				52,
																				52)
																		.addComponent(
																				jButton2,
																				javax.swing.GroupLayout.PREFERRED_SIZE,
																				31,
																				javax.swing.GroupLayout.PREFERRED_SIZE)))
										.addContainerGap()));
	}// </editor-fold>//GEN-END:initComponents

	private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {// GEN
		// -
		// FIRST
		// :
		// event_listValueChanged
		if (!evt.getValueIsAdjusting())
			fireItemsSelected();
	}// GEN-LAST:event_listValueChanged

	private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-
		// FIRST
		// :
		// event_jButton1ActionPerformed
		if (step == null || step.getName().equals(""))
			JOptionPane.showMessageDialog(this,
					"No step defined. There is nothing to save.");
		else if (getSelectedClasses().length == 0)
			JOptionPane
					.showMessageDialog(
							this,
							"No class selected so there is nothing to save. \nIf you disabled this step there is no need to save it, it is saved automaticaly.");
		else
			saveStep();
	}// GEN-LAST:event_jButton1ActionPerformed

	private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-
		// FIRST
		// :
		// event_jButton2ActionPerformed
		disableStep();
	}// GEN-LAST:event_jButton2ActionPerformed

	// Variables declaration - do not modify//GEN-BEGIN:variables
	protected javax.swing.JLabel description;
	protected javax.swing.JCheckBox isMultiple;
	private javax.swing.JButton jButton1;
	private javax.swing.JButton jButton2;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JLabel jLabel2;
	private javax.swing.JLabel jLabel3;
	private javax.swing.JLabel jLabel4;
	private javax.swing.JLabel jLabel5;
	private javax.swing.JScrollPane jScrollPane1;
	protected javax.swing.JList list;
	protected javax.swing.JLabel name;
	private rs.fon.rapidminer.gui.editor.Parameters parameters1;
	// End of variables declaration//GEN-END:variables

}
